package com.zee.admin.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.zee.admin.entity.SysLogLogin;
import com.zee.admin.entity.SysUser;
import com.zee.admin.enums.LoginOperationEnum;
import com.zee.admin.enums.LoginStatusEnum;
import com.zee.admin.enums.UserStatusEnum;
import com.zee.admin.model.dto.SysLoginDTO;
import com.zee.admin.model.response.AdminCode;
import com.zee.admin.service.ICaptchaService;
import com.zee.admin.service.ISysLogLoginService;
import com.zee.admin.service.ISysUserService;
import com.zee.admin.service.ISysUserTokenService;
import com.zee.admin.shiro.AdminSecurityUser;
import com.zee.admin.shiro.AdminUserDetail;
import com.zee.common.exception.ExceptionCast;
import com.zee.common.model.response.CommonCode;
import com.zee.common.model.response.Result;
import com.zee.common.utils.AssertUtil;
import com.zee.common.utils.IpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;

/**
 * 登录相关接口
 *
 * @author Mark LinZee
 * @email LinZee666@163.com
 */
@RestController
@RequestMapping("sys/index")
@Api(tags = "后台登录管理")
public class SysIndexController {
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysUserTokenService sysUserTokenService;
    @Autowired
    private ICaptchaService captchaService;
    @Autowired
    private ISysLogLoginService sysLogLoginService;

    @Value("${zee.captcha.open: true}")
    private boolean isOpenCaptcha;

    @GetMapping("captcha")
    @ApiOperation(value = "验证码", produces = "application/octet-stream")
    @ApiImplicitParam(paramType = "query", dataType = "string", name = "uuid", example = "8a3c1d2d-6694-443b-b865-1839e831d86d", required = true)
    public void captcha(HttpServletResponse response, String uuid) {
        if (!isOpenCaptcha) {
            ExceptionCast.cast(AdminCode.CAPTCHA_IS_NOT_ENABLED);
        }
        //uuid不能为空
        AssertUtil.isBlank(uuid, "uuid");

        //生成验证码
        try {
            captchaService.create(response, uuid);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    @PostMapping("login")
    @ApiOperation(value = "登录")
    @ApiOperationSupport(responses = @DynamicResponseParameters(properties = {
            @DynamicParameter(name = "token", value = "令牌"),
            @DynamicParameter(name = "expire", value = "过期秒数"),
            @DynamicParameter(name = "createTime", value = "创建时间"),
            @DynamicParameter(name = "expireTime", value = "过期时间"),
    }))
    public Result login(HttpServletRequest request, @Validated @RequestBody SysLoginDTO login) {
        //如果开启验证码，校验是否正确
        if (isOpenCaptcha) {
            AssertUtil.isBlank(login.getUuid(), "uuid");
            AssertUtil.isBlank(login.getCaptcha(), "验证码");
            boolean flag = captchaService.validate(login.getUuid(), login.getCaptcha());
            if (!flag) {
                return Result.error(AdminCode.CAPTCHA_ERROR);
            }
        }

        //用户信息
        SysUser user = sysUserService.getByUsername(login.getUsername());

        SysLogLogin log = new SysLogLogin();
        log.setOperation(LoginOperationEnum.LOGIN.value());
        log.setCreateTime(LocalDateTime.now());
        log.setIp(IpUtil.getIpAddr(request));
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        log.setIp(IpUtil.getIpAddr(request));

        //用户不存在
        if (user == null) {
            log.setStatus(LoginStatusEnum.FAIL.value());
            log.setCreatorName(login.getUsername());
            sysLogLoginService.save(log);

            ExceptionCast.cast(CommonCode.ACCOUNT_PASSWORD_ERROR);
        }

        //密码错误
        if (!user.getPassword().equals(DigestUtils.sha256Hex(login.getPassword()))) {
            log.setStatus(LoginStatusEnum.FAIL.value());
            log.setCreatorName(user.getUsername());
            sysLogLoginService.save(log);

            ExceptionCast.cast(CommonCode.ACCOUNT_PASSWORD_ERROR);
        }

        //账号停用
        if (user.getStatus() == UserStatusEnum.DISABLE.value()) {
            log.setStatus(LoginStatusEnum.LOCK.value());
            log.setCreatorName(user.getUsername());
            sysLogLoginService.save(log);

            ExceptionCast.cast(CommonCode.ACCOUNT_DISABLE);
        }

        //登录成功
        log.setStatus(LoginStatusEnum.SUCCESS.value());
        log.setCreatorName(user.getUsername());
        sysLogLoginService.save(log);

        return Result.ok(sysUserTokenService.createToken(user.getId()));
    }

    @PostMapping("logout")
    @ApiOperation(value = "退出")
    public Result logout(HttpServletRequest request) {
        AdminUserDetail user = AdminSecurityUser.getUser();
        //修改token，退出
        sysUserTokenService.logout(user.getId());

        //退出日志信息
        SysLogLogin log = new SysLogLogin();
        log.setOperation(LoginOperationEnum.LOGOUT.value());
        log.setIp(IpUtil.getIpAddr(request));
        log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
        log.setIp(IpUtil.getIpAddr(request));
        log.setStatus(LoginStatusEnum.SUCCESS.value());
        log.setCreatorName(user.getUsername());
        log.setCreateTime(LocalDateTime.now());
        sysLogLoginService.save(log);

        return Result.ok();
    }

}